Django 会員登録機能のテンプレ
Signup機能(メール連携付き)のテンプレート
メールで会員登録を促すタイプの新規会員登録
code: settings.py
LOGIN_REDIRECT_URL = '/' # ログイン後のリダイレクト先
LOGOUT_REDIRECT_URL = '/' # ログアウト後のリダイレクト先
LOGIN_URL = 'user:login' # ログインが必要な場合のリダイレクト先
# development
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# production
# Email (maybe, should change smtp host)
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
EMAIL_PORT = 587
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
code: urls.py
from django.urls import path
from . import views
app_name = 'user'
urlpatterns = [
path('signup/', views.SignupView.as_view(), name='signup'),
path('signup_done/', views.SignupDoneView.as_view(), name='signup_done'),
path('signup_complete/<token>', views.SignupCompleteView.as_view(), name='signup_complete'),
]
code: views.py
from django.views.generic import TemplateView, CreateView
from django.conf import settings
from django.urls import reverse_lazy
from django.views.defaults import bad_request
from django.template.loader import render_to_string
from django.shortcuts import redirect, render
from django.core.signing import BadSignature, SignatureExpired, loads, dumps
from django.contrib.sites.shortcuts import get_current_site
from django.conf import settings
from .forms import SignupForm
UserModel = get_user_model()
class SignupView(CreateView):
form_class = SignupForm
template_name = 'user/signup.html'
success_url = reverse_lazy('user:signup_done')
def form_valid(self, form):
user = form.save(commit=False)
user.is_active = False
user.save()
self.object = user
# アクティベートurlをメールで送信
current_site_domain = get_current_site(self.request).domain
context = {
'protocol': self.request.scheme,
'domain': current_site_domain,
'token': dumps(user.pk),
'user': user,
}
subject = render_to_string('user/mail/signup_subject.txt', context)
message = render_to_string('user/mail/signup_message.txt', context)
user.email_user(subject, message)
return redirect(self.get_success_url())
class SignupDoneView(TemplateView):
"""ユーザー仮登録"""
template_name = 'user/signup_done.html'
class SignupCompleteView(TemplateView):
"""ユーザー仮登録"""
template_name = 'user/signup_complete.html'
timeout_seconds = getattr(settings, 'ACTIVATION_TIMEOUT_SECONDS', 60 * 60 * 24)
def get(self, request, *args, **kwargs):
"""tokenが正しければ本登録"""
token = kwargs.get('token')
try:
user_pk = loads(token, max_age=self.timeout_seconds)
except SignatureExpired as e:
return bad_request(request, e, template_name='400.html')
except BadSignature as e:
return bad_request(request, e, template_name='400.html')
try:
user = UserModel.objects.get(pk=user_pk)
except UserModel.DoesNotExist as e:
return bad_request(request, e, template_name='400.html')
if not user.is_active:
# 問題なければ本登録とする
user.is_active = True
user.save()
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
return super().get(request, **kwargs)
return render(request, self.template_name, {})
code: models.py
class User:
...
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, self.email, **kwargs) code: forms.py
from django.contrib.auth.forms import UserCreationForm
class SignupForm(UserCreationForm):
def __init__(self, request=None, *args, **kwargs):
"""
The 'request' parameter is set for custom auth use by subclasses.
The form data comes in via the standard 'data' kwarg.
"""
self.request = request
self.user_cache = None
super().__init__(*args, **kwargs)
class Meta:
model = UserModel
fields = ('email', 'username', 'password1', 'password2')
def clean_email(self):
UserModel.objects.filter(email=email, is_active=False).delete()
return email
メール内容
code: user/mail/signup_message.txt
{{ user.email }} 様 会員登録手続きを行っていただき、ありがとうございます。
下記URLよりサイトにアクセスして本登録を行なってください。
まだ会員登録手続きは完了しておりませんので、ご注意ください。
本登録用URL
{{ protocol}}://{{ domain }}{% url 'user:signup_complete' token %}
普通のタイピング
code: user/mail/signup_subject.txt
普通のタイピング - 会員登録
html
code: user/signup.html
<form class="login_planeForm" action="{% url 'user:login' %}" method="post">
{% csrf_token %}
{% if form.errors %}
<ul class="valid-errors">
{% for error in form.non_field_errors %}
<li>{{ error }}</li>
{% endfor %}
{% for error in form.email.errors %}
<li>{{ error }}</li>
{% endfor %}
{% for error in form.password.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{{ form.email }}
{{ form.password }}
<button class="button">ログイン</button>
</form>
code: user/signup_done.html
<div class="body">
<main class="container">
<p>メールを送信しました。送信したurlにアクセスして本登録を行なってください。</p>
</main>
</div>
code: user/signup_complete.html
<div class="body">
<main class="container">
<p>本登録が完了しました!!</p>
<a href="{% url 'user:home' %}">ホームへ</a>
</main>
</div>